﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace DynamicHeader
{
    internal class DynamicHeaderFilter : Stream
    {
        private Stream orgFilter;

        public DynamicHeaderFilter(Stream orgFilter)
        {
            this.orgFilter = orgFilter;
        }

        public override bool CanRead
        {
            get { return false; }
        }

        public override bool CanSeek
        {
            get { return false; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override void Flush()
        {
            orgFilter.Flush();
        }

        public override long Length
        {
            get { throw new NotImplementedException(); }
        }

        public override long Position
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            throw new NotImplementedException();
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotImplementedException();
        }

        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }

        private bool proceeded = false;

        public override void Write(byte[] buffer, int offset, int count)
        {
            if (proceeded == false)
            {
                var dynamicHeader = DynamicHeader.GetInstance();
                if (dynamicHeader.IsWritenSignature == false)
                {
                    proceeded = true;
                }
                else
                {
                    // Find the signature ( "\b" x 4 ) that @Html.DynamicHeader() outputed.
                    var idx = Array.IndexOf(buffer, (byte)0x08, offset, count);
                    if (idx != -1 && (offset + count) > (idx + 4))
                    {
                        var sig = new byte[4];
                        Array.Copy(buffer, idx, sig, 0, 4);
                        if (Array.TrueForAll(sig, b => b == 0x08))
                        {
                            // Found signature, replace signature to the HTML that was registered by DynamicHeader.
                            proceeded = true;
                            orgFilter.Write(buffer, offset, idx - offset);

                            var html = dynamicHeader.GetHtml();
                            var injectBytes = Encoding.UTF8.GetBytes(html);
                            orgFilter.Write(injectBytes, 0, injectBytes.Length);

                            orgFilter.Write(buffer, idx + 4, count - 4 - (idx - offset));
                            return;
                        }
                    }
                }
            }

            orgFilter.Write(buffer, offset, count);
        }
    }
}
